#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "iot_export_linkkit.h"
#include "cJSON.h"
#include "smart_outlet.h"
#include "business.h"
#include "ugen_main.h"
#include  "ugen_config.h"

static int * ugen_add_value(uint8_t type,cJSON *root,char * Now_name,uint8_t *Now_value,uint8_t len)//填入json数据；
{
    switch (type)
    {
    case TYPE_BOOL:
    {
        cJSON_AddNumberToObject(root,Now_name,Now_value[0]);
        break;
    }
    case TYPE_UINT8_T:
    {
        cJSON_AddNumberToObject(root,Now_name,Now_value[0]);
        break;
    }
    case TYPE_UINT16_T:
    {
        cJSON_AddNumberToObject(root,Now_name,(Now_value[0]<<8) + Now_value[1]);
        break;
    }
    case TYPE_UINT32_T:
    {
        cJSON_AddNumberToObject(root,Now_name,((Now_value[0]<<24)+(Now_value[1]<<16)+(Now_value[2]<<8)+Now_value[3]));
        break;
    }
    case TYPE_INT8_T:
    {
        cJSON_AddNumberToObject(root,Now_name,0-Now_value[0]);
        break;
    }
    case TYPE_INT16_T:
    {
        cJSON_AddNumberToObject(root,Now_name,0-((Now_value[0]<<8)+Now_value[1]));
        break;
    }
    case TYPE_INT32_T:
    {
        cJSON_AddNumberToObject(root,Now_name,0-((Now_value[0]<<24)+(Now_value[1]<<16)+(Now_value[2]<<8)+Now_value[3]));
        break;
    }
    case TYPE_STRING:
    {
        char valuestr[60];
        int valuestr_len = 0;
        LOG_TRACE("TYPE_STRING :");
        for(int i = 0;i < len;i++)
        {
            valuestr_len = strlen(valuestr);
            snprintf(valuestr+valuestr_len,(60-valuestr_len),"%d",Now_value[i]);
            LOG_TRACE("%d",Now_value[i]);
        }
        LOG_TRACE("\nTYPE_STRING=:%s\n",valuestr);
        cJSON_AddStringToObject(root,Now_name,(char *)valuestr);
        break;
    }
    default:
        break;
    }
    
}
uint32_t sum_up_pro = 0;
uint32_t sum_up_suc = 0;
static int * ugen_up_value(uint8_t msg_type,cJSON *root,char * event_id)
{
    LOG_TRACE("ugen_up_value start");
    user_example_ctx_t *user_example_ctx = user_example_get_ctx();
    char *payload = "NULL";
    int res = 0;
    if(msg_type == UPPROPRETY)//属性
    {
        payload = cJSON_Print(root);
        res = IOT_Linkkit_Report(user_example_ctx->master_devid, ITM_MSG_POST_PROPERTY, (unsigned char *)payload, strlen(payload));//上报      
    }
    else//事件
    {
        LOG_TRACE("up start ;event_id =%s",event_id);
        payload = cJSON_PrintUnformatted(root);
        res = IOT_Linkkit_TriggerEvent(user_example_ctx->master_devid, event_id, strlen(event_id), (unsigned char *)payload, strlen(payload));
    }
    LOG_TRACE("payload=%s;;res =%d",payload,res);                                 
    aos_free(payload); //释放内存
    ////////////////////////
    ugen_up_reply(res,msg_type);//回复上报结果
    sum_up_pro ++;
    if(res)
    {
        //sum_up_suc ++;
        LOG_TRACE("----->up_true sum_up_pro=%d;;sum_up_suc=%d\r\n",sum_up_pro,sum_up_suc);   
    }
    else
    {
        LOG_TRACE("----->up_false\r\n");
    }
    return res;
}
// ////////////////
int get_ugen_config_value(uint8_t *data,uint8_t len)//mcu上报指令解析上报
{
    LOG_TRACE("get_ugen_config_value size_NowConfig--->:%d\n",sizeof(ugen_config));
    ugen_config *currency_config = get_ugen_config();
    uint8_t NowConfig_sum = 0;//指令含有属性事件数量
    uint8_t msg_len = data[2];//消息体总长度
    uint8_t msg_type = data[3];//上报类型
    uint8_t property_len = data[4];//单个属性或事件长度
    uint8_t *p = (data + 4);//总循环的指针开始位置
    uint8_t check_config = 0;//事件或属性在结构体位置
    LOG_TRACE("data[4]=%d;; *p =%d\n",property_len,*p);
//上报的json
    cJSON *root;
    root = cJSON_CreateObject();//a,b,1 {"a":}
    char *event_id = NULL;
    //////////////////////////////
    while(((msg_len - 1) > 0)&&(currency_config[check_config].name != NULL))//属性查找完没有或到长度最后结束
    {
        //LOG_TRACE("(msg_len - 1)=%d;;currency_config[check_config].name =:%s\n",(msg_len - 1),currency_config[check_config].name);
        if(((*(p + 1))<<8)+(*(p+2)) == (currency_config[check_config].data))//判断action
        {
            //LOG_TRACE("set pro :%d;;check_config=%d\n",NowConfig_sum,check_config);
            if(currency_config[check_config].value != TYPE_EVENT)
            {
                // uint8_t * Now_value = p+3;//属性值指针
                // char * Now_name = currency_config[check_config].name;
                ugen_add_value(currency_config[check_config].value,root,currency_config[check_config].name,(p+3),(property_len - 3));
            }
            else
            {   
                event_id = currency_config[check_config].name;
            }
            p += property_len;//总循环指针跳转到下一个参数
            msg_len -= property_len;//剩下的总长度
            property_len = *p;//len为下一个参数的字节长度
            NowConfig_sum ++;
            check_config = 0;
            continue;
            // break;
        }
        check_config ++;
    }

    if(NowConfig_sum != 0)
    {  
        ugen_up_value(msg_type,root,event_id);//上报云端
    }
    else
    {
        LOG_TRACE("NowConfig_sum == 0,not find");
        ugen_up_reply(NowConfig_sum,msg_type);
    }
    cJSON_Delete(root);  //释放内存
    return 0;
}

/*
static int ugen_uart_send_property(ugen_config * NowConfig,uint8_t * data,uint8_t len)
{
    LOG_TRACE("ugen_uart_send_property start\n");
    uint8_t cloude_buf[30];
    int cloude_buf_len = 7;
    if(NowConfig->value == TYPE_STRING)
    {
        char *value_string = get_str_value(data,NowConfig[0].name);
        int value_string_len = strlen(value_string);
        // bcd2hex((uint8_t *)value_string, cloude_buf);
        LOG_TRACE("string =%s;;string_len =%d\n",value_string,value_string_len);
        memcpy((cloude_buf+8),value_string,value_string_len);
        LOG_TRACE("buf =%s\n",(uint8_t *)cloude_buf);
        cloude_buf_len += value_string_len;
    }
    else
    {
        int32_t  value = get_value(data,(NowConfig->name));//获取属性值
        switch (NowConfig->value)
        {
            case TYPE_BOOL:
            {
                cloude_buf[7] = value;
                cloude_buf_len += 1;
                break;
            }
            case TYPE_UINT8_T:
            {
                cloude_buf[7] = value;
                cloude_buf_len += 1;
                break;
            }
            case TYPE_UINT16_T:
            {
                cloude_buf[7] = value>>8;
                cloude_buf[8] = value&0xFF;
                cloude_buf_len += 2;
                break;
            }
            case TYPE_UINT32_T:
            {
                cloude_buf[7] = value>>24;
                cloude_buf[8] = (value>>16)&0xFF;
                cloude_buf[9] = (value>>8)&0xFF;
                cloude_buf[10] = value&0xFF;
                cloude_buf_len += 4;
                break;
            }

            case TYPE_INT8_T:
            {
                cloude_buf[7] = value;
                cloude_buf_len += 1;
                break;
            }
            case TYPE_INT16_T:
            {
                cloude_buf[7] = value>>8;
                cloude_buf[8] = value&0xFF;
                cloude_buf_len += 2;
                break;
            }
            case TYPE_INT32_T:
            {
                cloude_buf[7] = value>>24;
                cloude_buf[8] = (value>>16)&0xFF;
                cloude_buf[9] = (value>>8)&0xFF;
                cloude_buf[10] = value&0xFF;
                cloude_buf_len += 4;
                break;
            }      
            default:
                return 0;
        }
    }
    cloude_buf[0] = DEVICE_CMD_HEAD;
    cloude_buf[2] = cloude_buf_len - 3;
    cloude_buf[3] = SETPROPRETY;
    cloude_buf[4] = cloude_buf_len - 4;
    cloude_buf[5] = (NowConfig->data)>>8;
    cloude_buf[6] = (NowConfig->data)&0xFF; 
    cloude_buf[1] = check_sum(cloude_buf,cloude_buf_len);
    ugen_uart_send(cloude_buf,cloude_buf_len); 
}
*/
static uint8_t * set_cloude_cmd(ugen_config NowConfig,cJSON * item,uint8_t *cloude_date_len)
{
    LOG_TRACE("ugen_uart_send_property start\n");
    uint8_t *cloude_buf = (uint8_t *)aos_malloc(sizeof(uint8_t) * RECV_UART_DATA_MAXLENGTH);
    uint8_t value_data_len = 0;
    switch (NowConfig.value)
    {
        case TYPE_BOOL:
        {
            value_data_len = 1;
            break;
        }
        case TYPE_UINT8_T:
        {
            value_data_len = 1;
            break;
        }
        case TYPE_UINT16_T:
        {
            value_data_len = 2;
            break;
        }
        case TYPE_UINT32_T:
        {
            value_data_len = 4;
            break;
        }

        case TYPE_INT8_T:
        {
            value_data_len = 1;
            break;
        }
        case TYPE_INT16_T:
        {
            value_data_len = 2;
            break;
        }
        case TYPE_INT32_T:
        {
            value_data_len = 4;
            break;
        } 
        case TYPE_STRING:
        {
            uint8_t *value_string = (uint8_t *)(item->valuestring);//get_str_value(data,NowConfig[0].name);
            uint8_t value_string_len = strlen(value_string);
            LOG_TRACE("string =%s;;string_len =%d\n",value_string,value_string_len);
            memcpy((cloude_buf+3),value_string,value_string_len);
            LOG_TRACE("buf =%s\n",(uint8_t *)cloude_buf);
            value_data_len = value_string_len;
        }     
        default:
            return 0;
    }

    if((value_data_len == 0) && (value_data_len > (RECV_UART_DATA_MAXLENGTH-4)))
    {
        LOG_TRACE("len error\n");
        return NULL;
    }
    *cloude_date_len += value_data_len + 3;
    // LOG_TRACE("*cloude_date_len =%d;;value_data_len=%d;;\n",*cloude_date_len,value_data_len);
    cloude_buf[0] = *cloude_date_len;
    cloude_buf[1] = (NowConfig.data)>>8;
    cloude_buf[2] = (NowConfig.data)&0xFF;
    if((NowConfig.value != TYPE_STRING))
    {
        int32_t  valueint = item->valueint;//获取属性值 1;//
        LOG_TRACE("valueint=%d",valueint);
        uint8_t value_data[8] = {0};
        memcpy(value_data,&valueint,value_data_len);
        for(int i = 0;i < value_data_len;i++)
        {
            cloude_buf[value_data_len+2-i] = value_data[i];
            //LOG_TRACE("cloude_buf[value_data_len+2-i] ==%d",cloude_buf[value_data_len+2-i]);
        }
    }
    return cloude_buf;
}

uint32_t sum_cloude = 0;
uint32_t sum_suc = 0;
int ugen_analysis_cloude_cmd(uint8_t *data,uint8_t len)
{
    LOG_TRACE("ugen_analysis_cloude_cmd :len=%d\n",len);
    ugen_config *currency_config = get_ugen_config();
    // uint8_t uart_buf[RECV_UART_DATA_MAXLENGTH] = {DEVICE_CMD_HEAD,0xFF,0xFF,SETPROPRETY};
    uint8_t *uart_buf = (uint8_t *)aos_malloc(sizeof(uint8_t)*RECV_UART_DATA_MAXLENGTH);
    if(uart_buf == NULL)
    {
        LOG_TRACE("uart_buf is NULL\n");
        return 0;
    }

    uint8_t total_len = 4;//发送指令总长度
    uint8_t cloude_date_len = 0;//提取到属性的和标识的长度

    cJSON *root = NULL, *item = NULL;
    root = cJSON_Parse(data);//

    int i = 0;
	while((currency_config[i].name != NULL))
	{
		if(strstr(data,(currency_config[i].name)))
		{
            LOG_TRACE("property_good;name =%s\n",(currency_config[i].name));
            item = cJSON_GetObjectItem(root, (currency_config[i].name));	
            uint8_t *cloud_data = set_cloude_cmd(currency_config[i],item,&cloude_date_len);
            if((total_len > RECV_UART_DATA_MAXLENGTH) && cloude_date_len)
            {
                LOG_TRACE("value error\n");
                break;
            }
            //LOG_TRACE("memcpy start cloude_date_len=%d;;uart_buf + total_len=%d;\n",cloude_date_len,*(uart_buf + total_len));
            memcpy(uart_buf + total_len,cloud_data,cloude_date_len);
            aos_free(cloud_data);
            total_len += cloude_date_len;//长度增加
            cloude_date_len = 0;
		}
		i++;
	}
    ++sum_cloude;
	if(total_len > 4)
	{
        ++sum_suc;
        printf("sum =%d,sucess=%d\n",sum_cloude,sum_suc);
        uart_buf[0] = DEVICE_CMD_HEAD;
        uart_buf[3] = SETPROPRETY;
        uart_buf[2] = total_len - 3;
        uart_buf[1] = check_sum(uart_buf,total_len);
        ugen_uart_send(uart_buf,total_len);
#ifdef PROPERTY_AUTO_REPLY /*云端设置属性自动回复*/
        uart_buf[3] = UPPROPRETY;
        get_ugen_config_value(uart_buf,total_len);
#endif
	}
    else
    {
        LOG_TRACE("ugen_cloud_recv_handle Not find attr type.\n");
    }
    aos_free(uart_buf);
    cJSON_Delete(root);
    return 0;
}



/////////////////////////////////////////////////////////////////////////////

